package virtPresenter.model
{
	import com.adobe.cairngorm.control.CairngormEventDispatcher;
	
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.SecurityErrorEvent;
	import flash.events.StatusEvent;
	import flash.net.LocalConnection;
	
	import mx.controls.SWFLoader;
	
	import virtPresenter.event.CairngormErrorEvent;
	
	/**
	 * This class implements the proxy which is settled between the ui and the slide wrapper to increase performance.
	 * 
	 * @author: Sebastian Pospiech
	 */
	public class SlideWrapperProxy implements ISlideWrapperProxy
	{
		private var source:String;
		private var swf:SWFLoader;
		private var processingComplete:Boolean = true;
		private var localConSend:LocalConnection;
		private var localConRec:LocalConnection;
		private var lcConnectionSend:String;
		private var lcConnectionRec:String;
		private var locator:virtPresenterLocator = virtPresenterLocator.getInstance();
		
		private static var LC_ANIM_METHOD:String ="goToAnimStep_lc";
		private static var LC_SLIDE_METHOD:String ="gotoSlide_lc";
		private static var LC_LECTURES_METHOD:String = "setLecturesFolder_lc";
		
		private var requestStack:Array = new Array();
	
		/**
		 * Creates a proxy
		 * @param source: Source of swf-file
		 * @param lcConnectionSend: Name of the local Connection to send on
		 * @param lcConnectionRec: Name of the local Connection for receiving data
		 */
		public function SlideWrapperProxy(source:String, lcConnectionSend:String, lcConnectionRec:String):void{
			this.source = source;
			this.lcConnectionSend = lcConnectionSend;
			this.lcConnectionRec = lcConnectionRec;
			establishConnection();
		}
		
		private function establishConnection():void{
			swf = new SWFLoader();
			swf.source = this.source;
			swf.buttonMode = true;
			swf.useHandCursor = false;
			swf.showBusyCursor = true;
			localConSend = new LocalConnection();
			localConSend.addEventListener(SecurityErrorEvent.SECURITY_ERROR, securityErrorEventHandler);
			localConSend.addEventListener(StatusEvent.STATUS, statusEventHandler);
			
			try{
				this.localConRec = new LocalConnection();
				this.localConRec.client = this;
				this.localConRec.connect(this.lcConnectionRec);
			}
			catch(err:Error){
				trace("Flex2SWFConnector. Error in recievingLC!");
				CairngormEventDispatcher.getInstance().dispatchEvent(new CairngormErrorEvent(err,"A: Fehler in recievingLC. Evtl. läuft der virtPresenter bereits in Ihrem Browser. Bitte schließen Sie dann diese Version. Momentan ist es nur erlaubt eine Instanz des virtPresenter zur Zeit laufen zu lassen. Wir bitten um Entschuldigung für jegliche dadurch entstehende Unannehmlichkeiten!"));							
			}
		}
		
		public function getSWF():SWFLoader{
			return this.swf;
		}
		
		private function securityErrorEventHandler(e:SecurityErrorEvent):void{
			trace("securityErrorEventHandler: " + e);
		}
		
		private function statusEventHandler(e:StatusEvent):void{
			trace("StatusEventHandler: " + e);
		}
		
		public function requestSlide(slideNumber:int):void{
			var request:Array = new Array(LC_SLIDE_METHOD, slideNumber);
			requestStack.push(request);
			if (processingComplete)
				processRequests();
		}
		
		public function requestLecture(lecture:String):void{
			//lecture changes are not buffered, since they are not requested in a 
			//huge amount at a short time
			localConSend.send(lcConnectionSend, LC_LECTURES_METHOD, lecture);
		}
		
		public function requestAnim(animStepNumber:int):void{
			var request:Array = new Array(LC_ANIM_METHOD, animStepNumber);
			requestStack.push(request);
			if (processingComplete) 
				processRequests();
		}
		
		/**
		 * The Method on which the receiving lc receives date
		 */
		public function processed(type:String):void{
			trace("processed request: " + this.source);
			processingComplete = true;
			processRequests();
		}
		
		private function processRequests():void{
			if (requestStack.length == 0) return;
			processingComplete = false;
			var lastRequest:Array = requestStack.pop();
			trace("processingRequest");
			if (lastRequest[0].toString().match(LC_SLIDE_METHOD)){
				trace("throwing away "+requestStack.length +" requests");
				trace("request slide: "+lastRequest[1]);
				localConSend.send(lcConnectionSend, LC_SLIDE_METHOD, Number(lastRequest[1]));
				this.requestStack = new Array();
		}   else {
				var slideRequest:Array = slideLookup();
				trace("throwing away "+requestStack.length +" requests");
				this.requestStack = new Array();
				trace("request anim: "+lastRequest[1]);
				if (slideRequest!=null)
					localConSend.send(lcConnectionSend, LC_SLIDE_METHOD, Number(slideRequest[1]));
				localConSend.send(lcConnectionSend, LC_ANIM_METHOD, Number(lastRequest[1]));
			}
		}
		
		private function slideLookup():Array{
			if (requestStack.length == 0) return null;
			var tmp:Array = requestStack.pop();
			while (tmp[0].toString().match(LC_ANIM_METHOD)){
				if (requestStack.length == 0) return null;
				tmp = requestStack.pop();
			}
			return tmp;
		}
	}
}